package tbs.framework.sql.config;

import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.transaction.PlatformTransactionManager;
import tbs.framework.base.utils.LogFactory;
import tbs.framework.interfaces.IChainProvider;
import tbs.framework.sql.aop.FrameworkMapperAOP;
import tbs.framework.sql.constants.OrderConstant;
import tbs.framework.sql.ef.IEntityQueryWrapper;
import tbs.framework.sql.ef.impl.SimpleEntityQueryWrapper;
import tbs.framework.sql.extractor.ISelectSqlDialect;
import tbs.framework.sql.logger.ISqlLogger;
import tbs.framework.sql.logger.impl.NoSqlLogger;
import tbs.framework.sql.mapper.impl.EntitySelectFetchMapper;
import tbs.framework.sql.mapper.impl.FetchMapper;
import tbs.framework.sql.order.impl.AscStaticOrder;
import tbs.framework.sql.order.impl.DescStaticOrder;
import tbs.framework.sql.order.impl.OrderedModelOrderImpl;
import tbs.framework.sql.properties.SqlProperty;
import tbs.framework.sql.provider.impl.BuiltInValueConvertChainProvider;
import tbs.framework.sql.query.ISqlAssembler;
import tbs.framework.sql.query.impl.DefaultSqlAssembler;
import tbs.framework.sql.utils.QueryUtil;
import tbs.framework.sql.utils.TransactionUtil;
import tbs.framework.utils.BeanUtil;
import tbs.framework.utils.impls.Slf4JLoggerFactory;
import tk.mybatis.spring.annotation.MapperScan;

import javax.annotation.Resource;

/**
 * @author abstergo
 */
@MapperScan(basePackageClasses = EntitySelectFetchMapper.class)
public class SqlConfig {

    public static final String SQL_LOG_FACTORY_BEAN_NAME = "sqlLogFactory";

    @Resource
    SqlProperty sqlProperty;


    @Bean
    FrameworkMapperAOP frameworkMapperAOP() {
        return new FrameworkMapperAOP();
    }

    @Bean
    FetchMapper fetchMapper() {
        return new FetchMapper();
    }

    @Bean
    public ISqlAssembler systemSqlAssembler() throws Throwable {
        return BeanUtil.buildBeanFromProperties(new DefaultSqlAssembler(), sqlProperty.getSqlAssemblerType(), null);
    }


    @Bean
    public QueryUtil sqlUtil(ISelectSqlDialect dialect, ISqlAssembler sqlAssembler) {
        return new QueryUtil(dialect, sqlProperty, sqlAssembler);
    }
    @Bean
    public IChainProvider defaultvalueMappingProvider() {
        return new BuiltInValueConvertChainProvider();
    }

    @Bean
    public TransactionUtil transactionUtil(PlatformTransactionManager transactionManager) {
        return new TransactionUtil(transactionManager);
    }

    @Bean(SQL_LOG_FACTORY_BEAN_NAME)
    public LogFactory sqlLogFactory() {
        return new Slf4JLoggerFactory();
    }

    @Bean
    @ConditionalOnProperty(name = "tbs.framework.sql.enable-log-interceptor", havingValue = "true")
    SqlLoggingInterceptor sqlLoggingInterceptor() {
        return new SqlLoggingInterceptor();
    }

    @Bean
    @ConditionalOnProperty(name = "tbs.framework.sql.enable-auto-fill-value-interceptor", havingValue = "true")
    SqlAutoFillIntercepter autoFillIntercepter() {
        return new SqlAutoFillIntercepter();
    }

    @Bean
    @ConditionalOnMissingBean(ISqlLogger.class)
    @ConditionalOnBean(SqlLoggingInterceptor.class)
    public ISqlLogger defaultSqlLogger() throws Throwable {
        return BeanUtil.buildBeanFromProperties(new NoSqlLogger(), sqlProperty.getSqlLoggerType(), null);
    }

    @Bean(OrderConstant.ASC)
    public AscStaticOrder ascOrder() {
        return new AscStaticOrder();
    }

    @Bean(OrderConstant.DESC)
    public DescStaticOrder descOrder() {
        return new DescStaticOrder();
    }

    @Bean(OrderConstant.ORDERED_MODEL)
    public OrderedModelOrderImpl orderedModelOrderImpl() {
        return new OrderedModelOrderImpl();
    }

    @Bean
    @Scope("prototype")
    IEntityQueryWrapper entityWrapper() {
        return new SimpleEntityQueryWrapper();
    }
}
